package com.carrental.api.ums.service;

import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.carrental.api.common.exception.Assert;
import com.carrental.api.ums.domain.bo.UmsRegisterBo;
import com.carrental.common.exception.OperationException;
import com.carrental.api.ums.domain.UmsUser;
import com.carrental.api.ums.domain.bo.UmsLoginBo;
import com.carrental.common.constant.Constants;
import com.carrental.common.utils.StpUmsUtil;
import com.carrental.common.utils.redis.RedisUtils;
import com.carrental.framework.config.AliyunSmsConfig;
import com.carrental.framework.config.TelephoneCodeConfig;
import com.carrental.sms.domain.SmsInfo;
import com.carrental.sms.servicce.AliyunSmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author LiangYi
 * @since 2022/3/23 21:56
 */
@Service
@Slf4j
public class IUmsUserLoginService {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private TelephoneCodeConfig telephoneCodeConfig;
    @Autowired
    private IUmsUserService userService;
    @Autowired
    private SaTokenConfig saTokenConfig;
    @Autowired
    private AliyunSmsConfig smsConfig;
    @Autowired
    private AliyunSmsService aliyunSmsService;

    public String login(UmsLoginBo loginUser) {
        Assert.notNull(loginUser.getTelephone(), "请输入手机号");
        Assert.notNull(loginUser.getCode(), "请输入验证码");
        String telephone=loginUser.getTelephone();
        String code=loginUser.getCode();
        //TODO 去redis拿验证码
        UmsUser user=userService.getUserByTelephone(telephone);
        Assert.notNull(user,"该手机号尚未注册！");
        //登录并生成token
        log.info("satoken配置信息："+saTokenConfig.toString());
        StpUmsUtil.login(user.getUserId());
        return StpUmsUtil.getTokenValue();
    }

    public Boolean register(UmsRegisterBo registerBo) {
        log.info(BCrypt.hashpw("123456"));
        log.info(String.valueOf(BCrypt.checkpw("123456","$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2")));
        Assert.notNull(registerBo.getTelephone(), "请输入手机号");
        Assert.notNull(registerBo.getCode(), "请输入验证码");
        String telephone=registerBo.getTelephone();
        String code=registerBo.getCode();
        //TODO 去redis拿验证码
        checkCode(telephone,code);
        UmsUser user=userService.getUserByTelephone(telephone);
        Assert.isNull(user,"该手机号已注册！");

        registerBo.setPassword(BCrypt.hashpw(registerBo.getPassword()));
        user=new UmsUser();
        BeanUtils.copyProperties(registerBo,user);
        if(!this.userService.save(user)){
            throw new OperationException("注册失败!");
        }
        //注册成功
        return true;
    }

    public Boolean sendCode(String telephone) {
        Assert.notNull(telephone, "请输入手机号");
        //TODO 生成四位验证码 去redis存验证码
        String code = RandomUtil.randomNumbers(4);
        String key = Constants.TELEPHONE_CAPTCHA_CODE_KEY + telephone;
        Integer limit = Constants.CAPTCHA_EXPIRATION;
        RedisUtils.setCacheObject(key, code, limit, TimeUnit.MINUTES);
        log.info("阿里云短信配置："+smsConfig.toString());
        //TODO 通过邮箱或短信给用户发送验证码...
        SmsInfo smsInfo=new SmsInfo();
        Map<String,String> map=new HashMap<>(8);
        map.put("code",code);
        smsInfo.setTemplateParam(JSON.toJSONString(map));
        smsInfo.setPhoneNumber(telephone);
        try{
            aliyunSmsService.sendSms(smsInfo);
        }catch (Exception e){
            throw new OperationException("验证码发送失败！");
        }
        return true;
    }

    public Boolean checkCode(String telephone,String code){
        String redisCode=RedisUtils.getCacheObject(Constants.TELEPHONE_CAPTCHA_CODE_KEY+telephone);
        if(redisCode==null){
            throw new OperationException("验证码已过期！");
        }
        if(!redisCode.equals(code)){
            throw new OperationException("验证码错误！");
        }
        return true;
    }
}
